<?php
/**
 * Hesperos library for Zend Framework
 *
 * This script is protected by copyright. It's use, copying, modification
 * and distribution without written consent of the author is prohibited.
 *
 * @category    Hesperos
 * @package     Filter
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt  GNU Lesser General Public
 * @version     1.0 $Id$
 * @link        http://code.google.com/p/hesperos/
 */

/**
 * Filtrowanie treści html, łamanie tekstu względem znacznika <hr />
 *
 * @category    Hesperos
 * @package     Filter
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @version     1.0 $Id$
 */
class Hesperos_Filter_PageBreak implements Zend_Filter_Interface
{
    /**
     * Filtrowanie treści zawierajacej paginacje na podstawie znacznika hr
     *
     * @todo Zabezpieczenie przed blednymi znacznikami html np.: <tag < >>
     * @param string $value
     * @return string
     */
    public function filter($value)
    {
        $pattern = array(
            '/<\/!.*?>/si',
            '/<\/\s*>/si',
            '/<!--.*?-->/si',
            '/\/\s+>/',
            '/<([a-z]+)\/>/si'
        );

        $replacement = array(
            '',
            '',
            '',
            '/>',
            '<$1 />'
        );

        $pageBreak = 'hr';
        $value = preg_replace($pattern, $replacement, $value);
        $openTags = array();
        $offset = 0;
        $lenght = mb_strlen($value, 'UTF-8');
        while(($open = mb_strpos($value, '<', $offset, 'UTF-8')) !== false) {
            /** Pozycja znaku zamykajacego znacznik **/
            $closePos = mb_strpos($value, '>', $open, 'UTF-8');

            /** W przypadku nieprawidlowosci pomijamy bierzacy fragment **/
            $vOpenPos = mb_strpos($value, '<', $open+1, 'UTF-8');
            if(!preg_match('/^[a-z\/]$/si', mb_substr($value, $open+1, 1, 'UTF-8'))) {
                $offset   = $open+1;
                continue;
            } else if($vOpenPos !== false && $vOpenPos < $closePos) {
                $offset   = $open+1;
                continue;
            }

            /** Zamykanie znacznika **/
            if(mb_substr($value, $open+1, 1, 'UTF-8') == '/') {
                $tagname  = mb_substr($value, $open+2, $closePos-$open-2, 'UTF-8');
                $offset   = $closePos;
                $end = end($openTags);

                if($end['name'] == $tagname) {
                    unset($openTags[key($openTags)]);
                } else {
                    $text   = mb_substr($value, 0, $open, 'UTF-8');
                    $offset = mb_strlen($text, 'UTF-8');
                    $text  .= mb_substr($value, $closePos+1, (mb_strlen($value)-$closePos-1), 'UTF-8');
                    $value = $text;
                }
            /** Otwieranie znacznika **/
            } else {
                $spacePos = mb_strpos($value, ' ', $open, 'UTF-8');
                $endPos   = ($closePos > $spacePos && $spacePos !== false) ? $spacePos : $closePos;
                $offset   = $closePos;
                $tagname  = mb_substr($value, $open+1, $endPos-$open-1, 'UTF-8');

                /** Znacznik dzielenia tekstu **/
                if($tagname == $pageBreak) {
                    /** Operacje zamkniecia otwartych tagow a nastepnie ponowne otworzenie **/
                    $text = mb_substr($value, 0, $open, 'UTF-8');
                    $openedTags = array_reverse($openTags);
                    foreach($openedTags as $tag) {
                        $text .= '</' . $tag['name'] . '>';
                    }
                    $text .= '<' . $pageBreak . ' />';
                    foreach($openTags as $tag) {
                        $text .= '<' . $tag['name'] . $tag['content'] . '>';
                    }
                    $offset = mb_strlen($text, 'UTF-8');
                    $text  .= mb_substr($value, $closePos+1, (mb_strlen($value)-$closePos-1), 'UTF-8');
                    $value = $text;
                /** Znacznik **/
                } else if(mb_substr($value, $closePos-1, 1, 'UTF-8') != '/') {
                    if($closePos > $spacePos && $spacePos !== false) {
                        $tagcontent = mb_substr($value, $spacePos, $closePos-$spacePos, 'UTF-8');
                    } else {
                        $tagcontent = null;
                    }
                    $openTags[] = array(
                        'name' => $tagname,
                        'content' => $tagcontent
                    );
                }
            }
        }
        if(!empty($openTags)) {
            $openedTags = array_reverse($openTags);
            /** Domykamy otwarte tagi **/
            foreach($openedTags as $tag) {
                $value .= '</' . $tag['name'] . '>';
            }
        }

        return $value;
    }
}